package com.small.site.service.impl;

import com.google.common.collect.Lists;
import com.small.site.base.IRoleService;
import com.small.site.base.IUserRoleService;
import com.small.site.base.IUserService;
import com.small.site.enums.ResponseCode;
import com.small.site.exception.BusinessException;
import com.small.site.ibase.IBaseService;
import com.small.site.pojo.SysUser;
import com.small.site.pojo.SysUserRole;
import com.small.site.service.UserService;
import com.small.site.util.Builder;
import com.small.site.util.IdWorker;
import com.small.site.util.R;
import com.small.site.vo.PageVo;
import com.small.site.vo.req.UserOwnRoleReqVo;
import com.small.site.vo.req.UserOwnRoleRespVo;
import com.small.site.vo.req.UserPageReqVo;
import com.small.site.vo.req.UserReqVo;
import com.small.site.vo.req.UserUpdatePasswordReqVo;
import com.small.site.vo.resp.UserRespVo;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.util.Date;
import java.util.List;

/**
 * @author xiaochi
 * @date 2021/12/14 15:13
 * @desc UserServiceImpl
 */
@Service
@SuppressWarnings("all")
public class UserServiceImpl implements UserService {

    @DubboReference(check = false)
    private IUserService userService;
    @DubboReference(check = false)
    private IRoleService roleService;
    @DubboReference(check = false)
    private IUserRoleService userRoleService;
    @Autowired
    private IdWorker idWorker;
    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    /**
     * 根据用户名查询用户
     * @param username
     * @return
     */
    @Override
    public SysUser getUserByUserName(String username) {
        SysUser sysUser = userService.findOne(SysUser.builder().username(username).build());
        return sysUser;
    }

    /**
     * 分页查询用户接口
     * @param userPageReqVo
     * @return
     */
    @Override
    public PageVo<SysUser> pageInfo(UserPageReqVo userPageReqVo) {
        IBaseService.Criteria<SysUser> criteria = userService.createCriteria(SysUser.class);
        criteria.andLike(SysUser::getUsername,StringUtils.isNotBlank(userPageReqVo.getUsername()),"%"+userPageReqVo.getUsername()+"%")
                .andLike(SysUser.Fields.nickName,StringUtils.isNotBlank(userPageReqVo.getNickName()),"%"+userPageReqVo.getNickName()+"%")
                .andEqualTo(SysUser.Fields.status, !ObjectUtils.isEmpty(userPageReqVo.getStatus()),userPageReqVo.getStatus())
                .andGreaterThanOrEqualTo(SysUser.Fields.createTime, !ObjectUtils.isEmpty(userPageReqVo.getStartTime()),userPageReqVo.getStartTime())
                .andLessThanOrEqualTo(SysUser.Fields.createTime, !ObjectUtils.isEmpty(userPageReqVo.getEndTime()),userPageReqVo.getEndTime())
                .andEqualTo(SysUser.Fields.deleted,1)
                .orderBy(SysUser::getCreateTime);
        return userService.findPage(userPageReqVo.getPageNum(),userPageReqVo.getPageSize(), criteria);
    }

    /**
     * 新增用户接口
     * @param sysUser
     * @return
     */
    @Override
    public R<String> createUser(SysUser sysUser) {
        sysUser.setId(String.valueOf(idWorker));
        int result = userService.insert(sysUser);
        if (result == 0){
            return R.error();
        }
        return R.ok();
    }

    /**
     * 查询用户拥有的角色数据接口
     * @param userId
     * @return
     */
    @Override
    public UserOwnRoleRespVo getUserOwnRole(String userId) {
        return Builder.of(UserOwnRoleRespVo::new)
                .with(UserOwnRoleRespVo::setOwnRoleIds,roleService.getRoleIdsByUserId(userId))
                .with(UserOwnRoleRespVo::setAllRole,roleService.findAll())
                .build();
    }

    /**
     * 保存用户拥有的角色信息接口
     * @param userOwnRoleReqVo
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<String> setUserOwnRole(UserOwnRoleReqVo userOwnRoleReqVo) {
        if (StringUtils.isBlank(userOwnRoleReqVo.getUserId())) {
            throw new BusinessException(ResponseCode.DATA_ERROR);
        }
        // 先删除用户原来的拥有的角色id
        userRoleService.removeRoleIdsByUserId(userOwnRoleReqVo.getUserId());
        if (userOwnRoleReqVo.getRoleIds().isEmpty()) {// 为空表示去除该用户所有角色
            return R.ok();
        }
        // 批量插入用户角色数据
        Date date = new Date();
        List<SysUserRole> data = Lists.newArrayList();
        for (String roleId : userOwnRoleReqVo.getRoleIds()) {
            data.add(SysUserRole.builder()
                    .id(String.valueOf(idWorker.nextId()))
                    .userId(userOwnRoleReqVo.getUserId())
                    .roleId(roleId)
                    .createTime(date)
                    .build());
        }
        int result = userRoleService.insertBatch(data);
        if (result == 0){
            throw new BusinessException(ResponseCode.ERROR);
        }
        return R.ok();
    }

    /**
     * 重置用户密码接口
     * @param userId
     * @return
     */
    @Override
    public R<String> resetUpdatePassword(String userId) {
        SysUser sysUser = userService.findOne(userId);
        if (sysUser == null){
            return R.error(ResponseCode.DATA_ERROR.getMessage());
        }
        int result = userService.updateById(SysUser.builder().id(sysUser.getId()).password(bCryptPasswordEncoder.encode("123456")).build());
        if (result == 0){
            return R.error();
        }
        return R.ok();
    }

    /**
     * 更新用户信息
     * @param userUpdateReqVo
     * @param userId
     * @return
     */
    @Override
    public R<String> updateUserInfo(UserReqVo userReqVo, String userId) {
        SysUser sysUser = userReqVo.buildEntity();
        if (StringUtils.isBlank(userReqVo.getPassword())){
            sysUser.setPassword(StringUtils.EMPTY);
        }else {
            sysUser.setPassword(bCryptPasswordEncoder.encode(userReqVo.getPassword()));
        }
        int result = userService.updateById(sysUser);
        if (result == 0){
            return R.error();
        }
        return R.ok();
    }

    /**
     * 批量/删除用户接口
     * @param list
     * @param userId 操作人
     * @return
     */
    @Override
    public R<String> deletedUsers(List<String> list, String userId) {
        SysUser sysUser = new SysUser();
        sysUser.setUpdateId(userId);
        sysUser.setUpdateTime(new Date());
        int result = userService.deletedUsers(sysUser,list);
        if (result == 0){
            return R.error();
        }
        return R.ok();
    }

    /**
     * 获取个人资料编辑信息
     * @param userId
     * @return
     */
    @Override
    public R<UserRespVo> detailInfo(String userId) {
        SysUser sysUser = userService.findOne(userId);
        UserRespVo userRespVo = new UserRespVo();
        BeanUtils.copyProperties(sysUser,userRespVo);
        return R.ok(userRespVo);
    }

    /**
     * 保存个人信息接口
     * @param sysUser
     * @param userId
     * @return
     */
    @Override
    public R<String> userUpdateDetailInfo(SysUser sysUser, String userId) {
        sysUser.setId(userId);
        sysUser.setUpdateId(userId);
        int result =  userService.updateById(sysUser);
        if (result == 0){
            return R.error();
        }
        return R.ok();
    }

    /**
     * 修改个人密码
     * @param userUpdatePasswordReqVo
     * @param userId
     * @return
     */
    @Override
    public R<String> userUpdatePassword(UserUpdatePasswordReqVo userUpdatePasswordReqVo, String userId) {
        SysUser sysUser = userService.findOne(userId);
        if (sysUser == null){
            return R.error(ResponseCode.TOKEN_NO_AVAIL.getMessage());
        }
        if (bCryptPasswordEncoder.matches(userUpdatePasswordReqVo.getOldPwd(),sysUser.getPassword())){
            return R.error(ResponseCode.OLD_PASSWORD_ERROR.getMessage());
        }
        sysUser.setUpdateId(userId);
        sysUser.setPassword(bCryptPasswordEncoder.encode(userUpdatePasswordReqVo.getNewPwd()));
        sysUser.setUpdateTime(new Date());
        int result = userService.updateById(sysUser);
        if (result == 0){
            return R.error();
        }
        return R.ok();
    }
}
